package com.whz.http.advice;

import com.whz.generic.api.ApiResponseWrapper;
import com.whz.generic.api.exception.CommonBusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;


/**
 * 异常处理类,应该更灵活的配置
 *
 * @author jiacheng
 */
@Slf4j
@ResponseBody
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    @ExceptionHandler(IllegalArgumentException.class)
    public ApiResponseWrapper<String> handle(IllegalArgumentException e) {
        log.error("[IllegalArgumentException] Illegal Argument.", e);
        return ApiResponseWrapper.fail(e.getMessage());
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(CommonBusinessException.class)
    public ApiResponseWrapper<CommonBusinessException> handle(CommonBusinessException e) {
        log.error("[TongyuBaseException] business exception.", e);
        return ApiResponseWrapper.whenFail(e);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public ApiResponseWrapper<String> handle(Exception e) {
        log.error("[Exception] service exception.", e);
        return ApiResponseWrapper.fail(e.getMessage());
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Throwable.class)
    public ApiResponseWrapper<String> handle(Throwable e) {
        log.error("[Throwable] service error.", e);
        return ApiResponseWrapper.fail(e.getMessage());
    }

    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResponseWrapper<String> handlerMethodArgumentNotValid(MethodArgumentNotValidException ex) {
        log.error("[MethodArgumentNotValidException] service error.", ex);
        String message = ex.getBindingResult().getFieldErrors().stream()
                           .map(ObjectError::getDefaultMessage)
                           .reduce((m1, m2) -> m1 + '；' + m2)
                           .orElse("参数输入有误！");

        return ApiResponseWrapper.fail(message);
    }

    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ApiResponseWrapper<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.error("[HttpMessageNotReadableException] service error.", ex);
        return ApiResponseWrapper.fail(ex.getMessage());
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(HttpMessageNotWritableException.class)
    public ApiResponseWrapper<String> handleHttpMessageNotWritableException(HttpMessageNotWritableException ex) {
        log.error("[HttpMessageNotWritableException] service error.", ex);
        return ApiResponseWrapper.fail(ex.getMessage());
    }
}